package syndication {
	import com.adobe.xml.syndication.NewsParser;
	import com.adobe.xml.syndication.atom.Atom03;
	import com.adobe.xml.syndication.atom.Atom10;
	import com.adobe.xml.syndication.atom.IAtom;
	import com.adobe.xml.syndication.atom.IEntry;
	import com.adobe.xml.syndication.atom.IFeedData;
	import com.adobe.xml.syndication.atom.Link;
	import com.adobe.xml.syndication.rss.IChannel;
	import com.adobe.xml.syndication.rss.IItem;
	import com.adobe.xml.syndication.rss.IRSS;
	import com.adobe.xml.syndication.rss.Item10;
	import com.adobe.xml.syndication.rss.Item20;
	import com.adobe.xml.syndication.rss.RSS10;
	import com.adobe.xml.syndication.rss.RSS20;
	
	/**
	 * Abstracts working with RSS or Atom feeds, but uses the language
	 * of RSS. For example, feeds are channels, and entries are items.
	 */
	public class Syndicate {
		public function Syndicate(data:String) {
			// Determine the type of syndicate RSS or Atom.
			// Try RSS 2.0 (and other version excep 1.0) specification.
			rss = new RSS20();
			rss.parse(String(data));

			if (!IRSS(rss).items) {
				// Try RSS 1.0 specication.
				rss = new RSS10();
				rss.parse(String(data));
				
				if (!IRSS(rss).items) {
					// Try Atom 1.0.
					rss = new Atom10();
					rss.parse(String(data));
					
					if (!IAtom(rss).entries) {
						//Try Atom 0.3
						rss = new Atom03();
						rss.parse(String(data));
						
						if (!IAtom(rss).entries) {
							rss = null;
						}		
					}
				}
			}
		}

		/**
		 * Get all items of RSS or entries of Atom. Both are
		 * represented by Item class.
		 */
		public function get items():Array {
			if (_items) {
				return _items;
			}
			
			var items:Array = new Array();
			
			// Try RSS			
			if (rss is IRSS) {
				var rssItems:Array = IRSS(rss).items;
				// For each RSS item determine if it's 1.0, 
				// or 2.0 (Item20 can handle other versions except 1.0).
				for each (var item:IItem in rssItems) {
					if (item is Item10) {
						items.push(new Item(item.title, item.link, 
											item.description, Item10(item).date.time));	
					} else {
						items.push(new Item(item.title, item.link, 
											item.description, Item20(item).pubDate.time));
					}
				}
				
				_items = items;
				
				return items;
			} else if (rss is IAtom) {
				// This is an Atom feed, so get all the entires.
				var atomEntries:Array = IAtom(rss).entries;
				
				for each (var entry:IEntry in atomEntries) {
					for each (var link:Link in entry.links) {
						if (link.rel == Link.REL_ALTERNATE) {
							items.push(new Item(entry.title, link.href, 
												entry.content.value, entry.published.time));
							break;
						}
					}
				}
				
				_items = items;
				
				return items;
			} else {
				return null;
			}
		}
		
		/**
		 * Get channel of RSS or feed of Atom. Both are represented
		 * by Channel class.
		 */
		public function get channel():Channel {
			if (_channel) {
				return _channel;
			}
			
			// If RSS, then get RSS's channel info.
			if (rss is IRSS) {
				_channel = new Channel(IChannel(IRSS(rss).channel).title, IChannel(IRSS(rss).channel).link);	
			} else if (rss is IAtom) {
				// If Atom, then get Atom's feed info.
				var feedData:IFeedData = IAtom(rss).feedData;
				_channel = new Channel(feedData.title.value, feedData.links[0].href);	
			} else {
				return null;	
			}
			
			return _channel;	
		}
		
		public function isValidSyndicate():Boolean {
			if (!items) {
				return false
			} else {
				return true;
			}
		}
		
		private var _items:Array;
		private var _channel:Channel;
		private var rss:NewsParser;
	}
}